﻿// 源文件头信息：
// <copyright file="EFRepositoryBase.cs">
// Copyright(c)2012-2019.
// CLR版本：4.0.30319.239
// 开发组织：luochengbang@163.com
// 公司网站：
// 所属工程：RH.EBS.Core
// 最后修改：Ben.Luo
// 最后修改：2014.09.22
// </copyright>

using RH.EBS.Core.Repository.Tools;
using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Data.Entity;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Data.Entity.Infrastructure;
using RH.EBS.Entitys;

namespace RH.EBS.Core.Repository
{
    /// <summary>
    ///     EntityFramework仓储操作基类
    /// </summary>
    /// <typeparam name="TEntity">动态实体类型</typeparam>
    public abstract class EFRepositoryBase<TEntity> : BaseContext<TEntity> where TEntity : Entity
    {
        public EFRepositoryBase(DbContext context)
            : base(context)
        { }
        #region 属性

        /// <summary>
        ///     获取 当前实体的查询数据集
        /// </summary>
        public virtual IQueryable<TEntity> Entities
        {
            get { return Context.Set<TEntity>(); }
        }

        #endregion

        #region 方法
        /// <summary>
        ///     插入实体记录
        /// </summary>
        /// <param name="entity"> 实体对象 </param>
        /// <returns> 操作影响的行数 </returns>
        public virtual TEntity Add(TEntity entity)
        {
            PublicHelper.CheckArgument(entity, "entity");
            return base.Add(entity);
        }

        /// <summary>
        ///     批量插入实体记录集合
        /// </summary>
        /// <param name="entities"> 实体记录集合 </param>
        /// <param name="isSave"> 是否执行保存 </param>
        /// <returns> 操作影响的行数 </returns>
        public virtual int Add(IEnumerable<TEntity> entities)
        {
            PublicHelper.CheckArgument(entities, "entities");
            return base.Add(entities);
        }

        /// <summary>
        ///     删除指定编号的记录
        /// </summary>
        /// <param name="id"> 实体记录编号 </param>
        /// <param name="isSave"> 是否执行保存 </param>
        /// <returns> 操作影响的行数 </returns>
        public virtual int Delete(object id)
        {
            PublicHelper.CheckArgument(id, "id");
            TEntity entity = base.Context.Set<TEntity>().Find(id);
            return entity != null ? Delete(entity) : 0;
        }

        /// <summary>
        ///     删除实体记录
        /// </summary>
        /// <param name="entity"> 实体对象 </param>
        /// <param name="isSave"> 是否执行保存 </param>
        /// <returns> 操作影响的行数 </returns>
        public virtual int Delete(TEntity entity)
        {
            PublicHelper.CheckArgument(entity, "entity");
            return base.Delete(entity);
        }

        /// <summary>
        ///     删除实体记录集合
        /// </summary>
        /// <param name="entities"> 实体记录集合 </param>
        /// <param name="isSave"> 是否执行保存 </param>
        /// <returns> 操作影响的行数 </returns>
        public virtual int Delete(IEnumerable<TEntity> entities)
        {
            PublicHelper.CheckArgument(entities, "entities");
            return base.Delete(entities);
        }

        /// <summary>
        ///     删除所有符合特定表达式的数据
        /// </summary>
        /// <param name="predicate"> 查询条件谓语表达式 </param>
        /// <param name="isSave"> 是否执行保存 </param>
        /// <returns> 操作影响的行数 </returns>
        public virtual int Delete(Expression<Func<TEntity, bool>> predicate)
        {
            PublicHelper.CheckArgument(predicate, "predicate");
            List<TEntity> entities = Context.Set<TEntity>().Where(predicate).ToList();
            return Delete(entities);
        }

        /// <summary>
        ///     更新实体记录
        /// </summary>
        /// <param name="entity"> 实体对象 </param>
        /// <param name="isSave"> 是否执行保存 </param>
        /// <returns> 操作影响的行数 </returns>
        public virtual TEntity Update(TEntity entity, bool isSave = true)
        {
            PublicHelper.CheckArgument(entity, "entity");
            return base.Update(entity);
        }

        /// <summary>
        ///     查找指定主键的实体记录
        /// </summary>
        /// <param name="key"> 指定主键 </param>
        /// <returns> 符合编号的记录，不存在返回null </returns>
        public virtual TEntity GetByKey(params object[] keyValues)
        {
            PublicHelper.CheckArgument(keyValues, "keyValues");
            return Context.Set<TEntity>().Find(keyValues);
        }

        /// <summary>
        /// 根据条件查询，返回一个实体
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="condition"></param>
        /// <returns></returns>
        public T GetBy<T>(Expression<Func<T, bool>> condition) where T : class
        {
            T entity = default(T);
            try
            {
                entity = Context.Set<T>().Where(condition).FirstOrDefault();
                return entity;
            }
            catch (Exception e)
            {
                ExceptionHand(e);
                return entity;
            }
        }

        /// <summary>
        /// 根据固定条件查询，返回一个实体集合
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="condition"></param>
        /// <returns></returns>
        public IQueryable<T> GetList<T, TOrderBy>(Expression<Func<T, bool>> condition, Expression<Func<T, TOrderBy>> orderby = null)
            where T : class
            where TOrderBy : class
        {
            try
            {
                if (orderby != null)
                {
                    return Context.Set<T>().Where(condition).OrderBy(orderby);
                }
                else
                {
                    return Context.Set<T>().Where(condition);
                }
            }
            catch (Exception e)
            {
                ExceptionHand(e);
                return null;
            }
        }

        public IQueryable<T> Paging<T>(IQueryable<T> iQueryable, PaginationDTO paginatonDTO)
           where T : class
        {
            if (paginatonDTO.ReCount)
            {
                paginatonDTO.RowCount = iQueryable.Count();
            }
            if (paginatonDTO.IsPaging)
            {
                iQueryable = iQueryable.OrderBy(c => 1 == 1).Skip(paginatonDTO.PageSize * (paginatonDTO.CurrentIndex - 1)).Take(paginatonDTO.PageSize);

            }
            return iQueryable;

        }


        /// <summary>
        /// 根据集合为某列合生成orelse连接条件 
        /// </summary>
        /// <typeparam name="TSource">集合项类型</typeparam>
        /// <param name="sourcePropertyName">数据库字段名</param>
        /// <param name="methodName">方法名称（IndexOf）</param>
        /// <param name="objs">条件数据集合</param>
        /// <returns></returns>
        public Expression<Func<TSource, bool>> GenerateOrElseConditionWithArray<TSource>(string sourcePropertyName, string methodName, IEnumerable<object> objs)
        {
            if (objs != null && objs.Count() > 0)
            {
                var len = objs.Count();
                var p = Expression.Parameter(typeof(TSource), "p");
                var propertyName = Expression.Property(p, sourcePropertyName);
                var body = Expression.GreaterThanOrEqual(Expression.Call(propertyName, methodName, null, Expression.Constant(objs.First())), Expression.Constant(0, typeof(int)));
                for (int i = 1; i < len; i++)
                {
                    var pcode = objs.ElementAt(i);
                    body = Expression.OrElse(body, Expression.GreaterThanOrEqual(Expression.Call(propertyName, methodName, null, Expression.Constant(pcode)), Expression.Constant(0, typeof(int))));//Expression.Call(propertyName, methodName, null, Expression.Constant(pcode)));
                }
                Expression<Func<TSource, bool>> orExp = Expression.Lambda<Func<TSource, bool>>(body, p);
                return orExp;
            }
            return null;
        }
        #endregion


    }
}